import { Injectable } from '@angular/core';
import { ApiService } from '@core/services/http/api.service';
import { ApesMessageService } from '@shared/apes/message';
import { SubjectService } from '@core/services/events/subject.service';
import { format } from 'date-fns';
import { deepClone, replaceAll } from '../../../utils/utils';
import { XlsxService } from '@shared/apes/xlsx';
import { ExpressionService } from '@core/services/expression/ExpressionService';

export interface DownloadType {
  id: string;
  api: string;
  col: any;
  ctx: any;
  name?: string;
  condition?: any;
  customQuery?: any;
}


@Injectable({
  providedIn: 'root',
})
export class DownloadService {

  constructor(
    private apiService: ApiService,
    private msg: ApesMessageService,
    private subject: SubjectService,
    private xlsx: XlsxService,
    protected expressionService: ExpressionService,
  ) {
  }

  startDownloadData(param: DownloadType) {
    let option = DownloadService.initDownloadOption(param);
    let data = [];
    let col = param.col;
    let ctx = param.ctx;
    if (option.printTemplate) {
      this.generateExcelTemplate(param, col);
    } else {
      this.queryDownloadData(data, option, col, ctx);
    }
  }

  private static initDownloadOption(param) {
    return {
      id: param.id,
      page: 0,
      percent: 0,
      size: 2000,
      condition: param.condition ? param.condition : [],
      queryid: param.api,
      queryname: param.name ? param.name : '导出文件',
      customAction: false,
      customQuery: param.customQuery ? param.customQuery :false,
      noSum: true,
      printTemplate: param.printTemplate,
    };
  }

  private queryDownloadData(data, option, col, ctx) {
    let totalQuantity = 300000; // 下载控制数
    let api = option.customQuery ? option.queryid : 'pub.query';

    this.apiService.post(api, { 'body': JSON.stringify(option) }).subscribe(
      (body) => {
        if (body) {
          //  total pages content
          if (body.total == 0) {
            this.msg.info(`查询结果为空`);
            this.showProgress(ctx, option, true);
            return;
          }

          body.content.forEach((i) => {
            data.push(i);
          });

          if (body.total > totalQuantity) {
            this.msg.info(`数据量过大！目前仅支持30W行以下数据下载`);
            this.showProgress(ctx, option, true);
            return;
          }

          if (body.total <= data.length) {
            this.generateExcel(data, option, col, ctx);
            option.percent = 100;

          } else {
            option.page = option.page + 1;
            option.percent = Math.round(option.page / body.pages * 100);
            this.queryDownloadData(data, option, col, ctx);
          }
          this.showProgress(ctx, option);
        } else {
          this.msg.info(`下载接口报错！`);
        }
      }, () => {
      });

  }

  private showProgress(ctx, option, empty?) {
    let progressData = {
      title: option.queryname,
      percent: empty ? 100 : option.percent,
    };

    this.subject.publish(ctx, 'progress_' + option.id, progressData);
  }

  private generateExcel(downloadData, option, col, ctx) {
    let exportName = option.queryname;
    exportName += format(new Date(), 'YYYYMMDDHHmm');
    let data = [];
    let localCol = [];
    let filterCol = [];
    filterCol = col.filter((i) => {
      if (i.hasOwnProperty('exportHide')) {
        let expression = i.exportHide;
        return !this.expressionService.evaluate(expression, {
          context: ctx,
        });
      } else {
        return true;
      }
    });
    data = [filterCol.map(i => i.headerName)];
    downloadData.forEach((i, index) => {
        if (index == 0) {
          let bExpansion = false;
          filterCol.map((c) => {
              let value = deepClone(i[c.field as string]);
              if (value instanceof Object) {
                localCol = [...localCol, ...this.objectToExpansion(value, c)];
                bExpansion = true;
              } else {
                c.fieldMeta = c.field;
                localCol.push(c);
              }
            },
          );
          if (bExpansion) data = [localCol.map(i => i.headerName)];
        }
        data.push(
          localCol.map(c => {
              let value = deepClone(i[c.fieldMeta as string]);
              let key = replaceAll(c.field, c.fieldMeta, '');
              if (value instanceof Object) {
                if (c['exportFormatter']) {
                  let expression = c['exportFormatter'];
                  value = this.expressionService.evaluate(expression, {
                    value: value,
                    data: i,
                  });
                } else {
                  value = value[key];
                }
                if (value == undefined) {
                  value = i[c.field as string].description;
                }
              } else {
                if (c['exportFormatter']) {
                  let expression = c['exportFormatter'];
                  value = this.expressionService.evaluate(expression, {
                    value: value,
                    data: i,
                  });
                }
              }
              // 处理序号字段为空的问题
              if (c.field === 'operation') value = data.length;

              return value;
            },
          ));
      },
    );
    this.xlsx.export({
      filename: exportName += '.xlsx',
      sheets: [
        {
          data: data,
          name: '数据',
        },
      ],
    });
  }

  private generateExcelTemplate(option, col) {
    let exportName = option.name;
    exportName += format(new Date(), 'YYYYMMDDHHmm');
    let data = [];
    data = [col.map(i => i.headerName)];
    if(option.hasOwnProperty('data')){
      let resData = option.data;
      resData.forEach((i)=>{
        data.push(
          col.map((c)=>{
            let value = deepClone(i[c.field as string]);
            return value
          })
        )
      })
    }

    this.xlsx.export({
      filename: exportName += '.xlsx',
      sheets: [
        {
          data: data,
          name: '数据',
        },
      ],
    });
  }

  objectToExpansion(value, c) {
    let columns = [];
    for (const key in value) {
      let localKey = key.toUpperCase();
      if (localKey == 'ID') {
        columns.push({ field: c.field + key, headerName: c.headerName + '编码', fieldMeta: c.field });
      } else if (localKey == 'NAME') {
        columns.push({ field: c.field + key, headerName: c.headerName + '名称', fieldMeta: c.field });
      }
    }
    return columns;
  }

}
